#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
import pandas as pd
import os

from pandas.core.frame import DataFrame
from PandasModel import PandasModel
from PyQt5 import QtCore, QtGui
import plotly.express as px
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtCore import QObject, QSize, pyqtSignal, QThread
from PyQt5.QtWidgets import (
    QDialog,
    QLabel,
    QWidget,
    QHBoxLayout,
    QLineEdit,
    QPushButton,
    QListWidgetItem,
    QVBoxLayout,
    QListWidget,
    QPlainTextEdit,
    QApplication,
    QGroupBox,
    QTabWidget,
    QFormLayout,
    QCheckBox,
    QTextEdit,
    QTableView,
    QFileDialog,
    QMessageBox,
    QGridLayout,
)


class ParseWorker(QThread):
    progressChanged = pyqtSignal(int)  # 值变化信号

    def run(self):
        print("thread id", QThread.currentThread())
        for i in range(0, 101, 50):
            if self.isInterruptionRequested():
                break
            print("value", i)
            self.progressChanged.emit(i)
            QThread.sleep(1)


class ItemWidget(QWidget):
    itemDeleted = pyqtSignal(QListWidgetItem)
    itemNickName = pyqtSignal(QListWidgetItem, str)

    def __init__(self, path, item, tableview, *args, **kwargs):
        super(ItemWidget, self).__init__(*args, **kwargs)
        self.path = path
        self._item = item  # 保留list item的对象引用
        self.dataFrame = DataFrame()
        self.tableview = tableview
        self.plotWindow = None

        self._parseThread = ParseWorker(self)
        self._parseThread.finished.connect(self.showTabview)
        self._parseThread.progressChanged.connect(self.updateProgress)

        # UI
        layout = QGridLayout(self)
        layout.setContentsMargins(5, 10, 5, 10)

        self.line = QLineEdit(path, self, editingFinished=self.nickname)
        layout.addWidget(self.line, 1, 0, 1, 2)

        layout.addWidget(QPushButton("删除", self, clicked=self.delete), 1, 2)
        layout.addWidget(QPushButton("打开", self, clicked=self.open), 1, 3)

        self.parseButton = QPushButton("解析", self, clicked=self.parse)
        layout.addWidget(self.parseButton, 2, 0)
        layout.addWidget(QPushButton("定位信息", self, clicked=self.plot), 2, 1)
        layout.addWidget(QPushButton("LS", self, clicked=self.plot), 2, 2)
        layout.addWidget(QPushButton("KF", self, clicked=self.plot), 2, 3)

    def updateProgress(self, progress):
        self.parseButton.setText("解析 %3d %%" % progress)

    def nickname(self):
        self.itemNickName.emit(self._item, self.line.text())

    def showTabview(self):
        self.dataFrame = pd.read_csv("./data.csv")
        self.tableview.setModel(PandasModel(self.dataFrame))

    def parse(self):
        # 启动线程
        if not self._parseThread.isRunning():
            print("main id:", QThread.currentThread())
            self._parseThread.start()

    def plot(self):
        if self.dataFrame.empty:
            QMessageBox.information(self, "提示", "没有解析出dataframe, 无法绘图")
            return

        if not self.plotWindow:
            fig = px.line(
                self.dataFrame, x="weeksecond", y=["trk", "acq", "reacq"], markers=True
            )

            self.plotWindow = QWidget()
            layout = QHBoxLayout()
            self.plotWindow.setLayout(layout)
            browser = QWebEngineView()
            layout.addWidget(browser)
            browser.setHtml(fig.to_html(include_plotlyjs="cdn"))

        self.plotWindow.show()

    def delete(self):
        self.itemDeleted.emit(self._item)

    def open(self):
        print(open)

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        # 关闭绘图的窗口
        if self.plotWindow:
            self.plotWindow.close()
        # 关闭线程
        if self._parseThread and self._parseThread.isRunning():
            self._parseThread.requestInterruption()
            self._parseThread.wait()
            self._parseThread.quit()
        return super().closeEvent(a0)

    # def sizeHint(self):
    #     # 决定item的高度
    #     return QSize(200, 1000)


class Window(QWidget):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        self.compareWindow = None
        # 整体的界面, 左边是控制台, 右边是tabwidget, 显示详细的内容
        layout = QHBoxLayout(self)
        controlLayout = QVBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        layout.addLayout(controlLayout)

        # 对比数据部分
        groupbox = QGroupBox("对比数据")
        controlLayout.addWidget(groupbox)
        compareLayout = QGridLayout()
        groupbox.setLayout(compareLayout)

        controlLayout.setSpacing(10)
        compareLayout.addWidget(
            QPushButton("Summary", self, clicked=self.onSummary), 1, 0
        )
        compareLayout.addWidget(
            QPushButton("上星", self, clicked=self.onCompareAcq), 1, 1
        )
        compareLayout.addWidget(
            QPushButton("峰形", self, clicked=self.onCompareShape), 1, 2
        )
        compareLayout.addWidget(
            QPushButton("时差", self, clicked=self.onCompareInnov), 1, 3
        )

        compareLayout.addWidget(
            QPushButton("LS", self, clicked=self.onCompareInnov), 2, 0
        )
        compareLayout.addWidget(
            QPushButton("KF", self, clicked=self.onCompareInnov), 2, 1
        )

        compareLayout.addWidget(
            QPushButton("捕获预测", self, clicked=self.onCompareInnov), 2, 2
        )

        compareLayout.addWidget(
            QPushButton("重补预测", self, clicked=self.onCompareInnov), 2, 3
        )

        # log 导入部分
        groupbox = QGroupBox("log 导入/清除")
        controlLayout.addWidget(groupbox)

        logLayout = QHBoxLayout()
        groupbox.setLayout(logLayout)

        # 添加
        logLayout.addWidget(QPushButton("添加", self, clicked=self.addItem))

        # 清空按钮
        logLayout.addWidget(QPushButton("清空", self, clicked=self.clearItems))

        # 列表
        self.listWidget = QListWidget(self, currentRowChanged=self.clickListItem)
        # self.listWidget.setSpacing(4)
        self.listWidget.setContentsMargins(0, 0, 0, 0)
        # self.listWidget.setStyleSheet(
        #     "QListWidget::item { border-bottom: 1px solid black; }"
        # )
        controlLayout.addWidget(self.listWidget)

        # 右侧详情
        detailGroupbox = QGroupBox("详情")
        layout.addWidget(detailGroupbox)

        detailLayout = QVBoxLayout()
        self.tabWidget = QTabWidget()
        detailLayout.addWidget(self.tabWidget)
        detailGroupbox.setLayout(detailLayout)

        layout.setStretch(0, 1)
        layout.setStretch(1, 3)
        self.resize(1500, 700)

    def clickListItem(self, item):
        # row = self.listWidget.indexFromItem(item).row()
        self.tabWidget.setCurrentIndex(item)

    def onSummary(self):
        dataframeList = []
        for i in range(self.listWidget.count()):
            item = self.listWidget.itemWidget(self.listWidget.item(i))
            if not item.dataFrame.empty:
                tmp = item.dataFrame.melt(
                    "weeksecond", var_name="type", value_name="num"
                )
                tmp["name"] = item.line.text()
                dataframeList.append(tmp)

        if not dataframeList:
            QMessageBox.information(self, "提示", "先导入数据并解析后, 再绘图")
            return

        dm = pd.concat(dataframeList)
        if dm.empty:
            QMessageBox.information(self, "提示", "检查数据的有效性")
            return

        if not self.compareWindow:
            self.compareWindow = QWidget()
            layout = QHBoxLayout()
            self.compareWindow.setLayout(layout)
            self.browser = QWebEngineView()
            layout.addWidget(self.browser)

        fig = px.line(
            dm,
            x="weeksecond",
            y="num",
            color="name",
            facet_row="type",
            markers=True,
            height=250 * 5,
        )
        fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
        fig.for_each_annotation(lambda a: a.update(font=dict(size=18)))
        fig.update_yaxes(matches=None)
        fig.for_each_xaxis(lambda x: x.update(visible=True))
        self.browser.setHtml(fig.to_html(include_plotlyjs="cdn"))

        self.compareWindow.show()

    def onCompareAcq(self):
        print("onCompareAcq")

    def onCompareInnov(self):
        print("onCompareInnov")

    def onCompareShape(self):
        print("onCompareShape")

    def addItem(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "选取文件", os.getcwd(), "All Files(*);;Text Files(*.txt)"
        )

        # tableview
        layout = QVBoxLayout()
        widget = QWidget()
        widget.setLayout(layout)
        tableview = QTableView(self)
        tableview.setSortingEnabled(True)
        layout.addWidget(tableview)
        self.tabWidget.addTab(widget, fileName)

        # listview
        item = QListWidgetItem(self.listWidget)
        widget = ItemWidget(fileName, item, tableview, self.listWidget)
        item.setSizeHint(widget.sizeHint())

        # 绑定信号
        widget.itemDeleted.connect(self.deleteItem)
        widget.itemNickName.connect(self.nicknameTab)

        self.listWidget.setItemWidget(item, widget)

    def nicknameTab(self, item, nickname):
        row = self.listWidget.indexFromItem(item).row()
        self.tabWidget.setTabText(row, nickname)

    def deleteItem(self, item):
        # close item对应的 widget
        self.listWidget.itemWidget(item).close()

        # 根据item得到它对应的行数
        row = self.listWidget.indexFromItem(item).row()
        # 删除item
        item = self.listWidget.takeItem(row)
        # 删除widget
        self.listWidget.removeItemWidget(item)
        # tabWidget里删除
        self.tabWidget.removeTab(row)

        del item

    def clearItems(self):
        # 清空所有Item
        for _ in range(self.listWidget.count()):
            self.listWidget.itemWidget(self.listWidget.item(0)).close()
            self.listWidget.takeItem(0)
            self.tabWidget.removeTab(0)

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        self.clearItems()
        if self.compareWindow:
            self.compareWindow.close()
        return super().closeEvent(a0)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())
